using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using 旅游管理系统.Database;
using 旅游管理系统.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Serialization;

namespace 旅游管理系统
{
    public class Startup
    {
        //配置服务的依赖
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; } //在构建函数中赋值

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services) //系统的 AOC容器，服务的依赖注册都是在这里进行的。
        {
            // AddControllers()帮助我们在创建api的时候向 auc容器中添加一个控制器的框架服务，
            //需要在 AddControllers()的参数中来对控制器进行配置从而来启动对 setup 的处理，在括号中使用  表达式，参数就是控制器的 action，
            services.AddControllers(setupAction =>
            {
                //添加 api对 XML格式的支持
                setupAction.ReturnHttpNotAcceptable = true; //取消对其他格式的支持
                //setupAction.OutputFormatters.Add(
                //    new XmlDataContractSerializerOutputFormatter() 
                //    );          //通过 OutputFormatters添加对 XML的支持 。是对XML格式的支持，还不能对XML的输出。
            })
            .AddNewtonsoftJson (setupAction =>
            {
                setupAction.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            }) //使用 PATCH部分更新资源
            .AddXmlDataContractSerializerFormatters()
            //添加可以控制 APIController行为的服务，这个服务就是用来配置一个叫做非法模型状态响应工厂(InvalidModelStateResponseFactory)这样的一个东西，简单来说就是用来验证数据是否非法这样的一个过程，
            .ConfigureApiBehaviorOptions(setupAction =>
            {
                setupAction.InvalidModelStateResponseFactory = context =>
                {
                    var problemDetail = new ValidationProblemDetails(context.ModelState)
                    {
                        //赋值
                        Type = "无所谓",
                        Title = "数据验证失败", //错误原因
                        Status = StatusCodes.Status422UnprocessableEntity, //状态码
                        Detail = "请看详细内容", //Detail 信息
                        Instance = context.HttpContext.Request.Path  //指的是请求路径
                    };
                    //给这个 problemDetail加上追踪 ID
                    problemDetail.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);
                    //返回422来代替400
                    return new UnprocessableEntityObjectResult(problemDetail)
                    {
                        //配置媒体类型contenttypes方便前端解析
                        ContentTypes = { "application/problem+json" }  //问题类型  此处 +号两端不能有空格，否则会报406错误
                    };
                };
            });
            //添加数据仓库的依赖注入
            services.AddTransient<ITouristRouteRepository,TouristRouteRepository>();
            //services.AddTransient<>(); 在每次发起请求时系统都会创建一个全新的数据仓库，而当请求结束后会自动注销这个仓库
            //services.AddSingleton<>(); 在发起请求时仅会创建一个数据仓库，之后的每次请求都会使用上创建的那个仓库
            //services.AddScoped<>(); 会将一系列的请求或操作放在一个事务中，发起请求时事务会创建一个数据仓库，所有请求或操作都会使用一个仓库，当这个事务结束后系统会注销这个事例。

            //上下文关系对象依赖注入
            services.AddDbContext<AppDbContext>(option =>
            {
                //系统自带的数据库
                //option.UseSqlServer(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=FakeXiechengDb;Integrated Security=True;Connect Timeout=30;Encrypt=False;Trust Server Certificate=False;Application Intent=ReadWrite;Multi Subnet Failover=False");
                //docker配置的数据库
                //option.UseSqlServer("server=localhost;Database=FakeXiechengDb;User Id=sa;password=123456;");
                option.UseSqlServer(Configuration["DbContext:ConnectionString"]);
            });

            //已经下载了 AutoMapper，可以直接调用 AutoMapper，需要在参数中填入目前系统的程序集
            // AutoMapper注册服务依赖的机制： AddAutoMapper会自动扫描所有包含映射关系的  profile 文件
            // AddAutoMapper会把所有的 profile文件加载到 AppDomain中    profile大致意思是 配置文件的意思。系统的映射机制就是通过 profile来管理的
            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}
